#define OfficePlugin

#if OfficePlugin
using OfficeOpenXml;
using OfficeOpenXml.Style;
#endif
using System;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEngine;

namespace CGF
{
    public class ExcelEditor
    {
        [MenuItem("CGFramework/导出多语言 Excel 表", priority = -960)]
        public static void Export()
        {
#if OfficePlugin
            string savePath = Application.dataPath.Replace("Unity/Assets", "");
            savePath = EditorUtility.SaveFilePanel("导出Excel表", savePath, "送翻译", "xlsx");
            if (string.IsNullOrEmpty(savePath)) return;

            List<List<string>> rows = new List<List<string>>();
            List<string> allPrefabPaths = new List<string>();
            //allPrefabPaths.Add("Assets/Res/Launch.prefab");
            string[] hotfixPrefabPaths = Directory.GetFiles($"{Application.dataPath}/{Define.BundleFolder}", "*.prefab", SearchOption.AllDirectories);
            allPrefabPaths.AddRange(hotfixPrefabPaths);
            for (int i = 0; i < allPrefabPaths.Count; i++)
            {
                string prefabPath = allPrefabPaths[i].Replace("\\", "/").Replace(Application.dataPath, "Assets");
                GameObject prefab = AssetDatabase.LoadAssetAtPath<GameObject>(prefabPath);
                I18N map = prefab.GetComponent<I18N>();
                if (map)
                {
                    prefabPath = prefabPath.Replace("Assets/", "").Replace(".prefab", "");
                    for (int j = 0; j < map.nodes.Count; j++)
                    {
                        I18N.Node node = map.nodes[j];
                        List<string> row = new List<string>();
                        row.Add(prefabPath);
                        row.Add(j.ToString());
                        for (int k = 0; k < node.indexLanguages.Count; k++)
                        {
                            row.Add(node.indexLanguages[k].ToString());
                        }
                        rows.Add(row);
                    }
                    for (int j = 0; j < map.keys.Count; j++)
                    {
                        List<string> row = new List<string>();
                        row.Add(prefabPath);
                        row.Add(map.keys[j]);
                        for (int k = 0; k < map.keyContents[j].languages.Count; k++)
                        {
                            row.Add(map.keyContents[j].languages[k]);
                        }
                        rows.Add(row);
                    }
                }
            }
            //保存到Excel
            FileInfo newFile = new FileInfo($"{savePath}");
            if (newFile.Exists) newFile.Delete();
            using (ExcelPackage package = new ExcelPackage(newFile))
            {
                ExcelWorksheet worksheet = package.Workbook.Worksheets.Add("Sheet0");
                worksheet.Row(1).Height = 30;
                worksheet.Row(1).Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;
                worksheet.Row(1).Style.VerticalAlignment = ExcelVerticalAlignment.Center;
                worksheet.Column(1).Width = 35;
                worksheet.Column(1).Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;
                worksheet.Column(1).Style.VerticalAlignment = ExcelVerticalAlignment.Center;
                worksheet.Column(2).Width = 30;
                worksheet.Column(2).Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;
                worksheet.Column(2).Style.VerticalAlignment = ExcelVerticalAlignment.Center;
                int langCount = Enum.GetValues(typeof(ELanguage)).Length;
                for (int c = 3; c <= langCount + 2; c++)
                {
                    worksheet.Column(c).Width = 30;
                    worksheet.Column(c).Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;
                    worksheet.Column(c).Style.VerticalAlignment = ExcelVerticalAlignment.Center;
                }
                worksheet.SetValue("A1", "预置体");
                worksheet.SetValue("B1", "索引/KEY");
                int col = 3;
                foreach (ELanguage language in Enum.GetValues(typeof(ELanguage)))
                {
                    worksheet.SetValue(1, col, language.ToString());
                    col++;
                }
                for (int i = 0; i < rows.Count; i++)
                {
                    List<string> row = rows[i];
                    worksheet.Row(i + 2).Height = 20;
                    worksheet.SetValue(i + 2, 1, row[0]);
                    worksheet.SetValue(i + 2, 2, row[1]);
                    col = Enum.GetValues(typeof(ELanguage)).Length - 2;
                    foreach (ELanguage language in Enum.GetValues(typeof(ELanguage)))
                    {
                        worksheet.SetValue(i + 2, col, row[col - 1]);
                        col++;
                    }
                }
                package.Save();
                Debug.Log("导出Excel表成功");
                //EditorUtility.DisplayDialog("提示", "导出Excel表成功", "确定");
            }
            I18NEditor.SavePrefabI18NToJson();
#endif
        }

        [MenuItem("CGFramework/导入多语言 Excel 表", priority = -950)]
        public static void Import()
        {
#if OfficePlugin
            Dictionary<string, List<List<string>>[]> allPrefabsData = new Dictionary<string, List<List<string>>[]>();
            //开始从Excel表读取数据
            string defaultPath = Application.dataPath.Replace("Unity/Assets", "");
            defaultPath = EditorUtility.OpenFilePanel("导入Excel表", defaultPath, "xlsx");
            if (string.IsNullOrEmpty(defaultPath)) return;

            bool sccess = true;
            using (ExcelPackage package = new ExcelPackage(new FileStream(defaultPath, FileMode.Open)))
            {
                for (int i = 0; i < package.Workbook.Worksheets.Count; ++i)
                {
                    ExcelWorksheet sheet = package.Workbook.Worksheets[i + 1];
                    for (int m = sheet.Dimension.Start.Row, n = sheet.Dimension.End.Row; m <= n; m++)
                    {
                        if (m > 1)
                        {
                            List<string> cols = new List<string>();
                            object col1Value = sheet.GetValue(m, 1);
                            if (col1Value == null)
                            {
                                Debug.LogError($"行{m}列1没有数据");
                            }
                            cols.Add(col1Value.ToString());
                            object col2Value = sheet.GetValue(m, 2);
                            if (col2Value == null)
                            {
                                Debug.LogError($"行{m}列2没有数据");
                            }
                            cols.Add(col2Value.ToString());
                            int col = 3;
                            while (true)
                            {
                                object contentObj = sheet.GetValue(m, col);
                                if (contentObj == null) break;
                                cols.Add(contentObj.ToString());
                                col++;
                            }
                            List<List<string>>[] configs = null;
                            string prefabPath = cols[0];
                            string indexOrKey = cols[1];
                            if (allPrefabsData.ContainsKey(prefabPath))
                            {
                                configs = allPrefabsData[prefabPath];
                            }
                            else
                            {
                                configs = new List<List<string>>[] { new List<List<string>>(), new List<List<string>>() };
                                allPrefabsData.Add(prefabPath, configs);
                            }
                            if (IsIndex(indexOrKey))
                            {
                                configs[0].Add(cols);
                            }
                            else
                            {
                                configs[1].Add(cols);
                            }
                        }
                    }
                }
            }

            //开始把数据写进预置体
            int completed = 0, total = allPrefabsData.Count;
            foreach (var prefabConfig in allPrefabsData)
            {
                string prefabPath = $"Assets/{prefabConfig.Key}.prefab";
                GameObject prefab = AssetDatabase.LoadAssetAtPath<GameObject>(prefabPath);
                if (prefab)
                {
                    I18N map = prefab.GetComponent<I18N>();
                    if (!map) map = prefab.AddComponent<I18N>();
                    List<List<string>> rows = prefabConfig.Value[0];
                    if (map.nodes.Count < rows.Count)
                    {
                        Debug.LogError($"{prefabPath}里的节点个数比Excel表少");
                        sccess = false;
                        break;
                    }
                    for (int i = 0; i < rows.Count; i++)
                    {
                        I18N.Node node = map.nodes[i];
                        List<string> colsData = rows[i];
                        for (int j = 2; j < colsData.Count; j++)
                        {
                            while (node.indexLanguages.Count - 1 < j - 2)
                            {
                                node.indexLanguages.Add("");
                            }
                            node.indexLanguages[j - 2] = colsData[j];
                        }
                    }

                    //自定义字段
                    List<List<string>> keyRows = prefabConfig.Value[1];
                    map.keys.Clear();
                    map.keyContents.Clear();
                    for (int i = 0; i < keyRows.Count; i++)
                    {
                        List<string> row = keyRows[i];
                        map.keys.Add(row[1]);
                        I18N.KeyContent cols = new I18N.KeyContent();
                        for (int j = 0; j < row.Count - 2; j++)
                        {
                            cols.languages[j] = row[j + 2];
                        }
                        map.keyContents.Add(cols);
                    }

                    //保存预置体
                    GameObject newPrefab = GameObject.Instantiate(prefab);
                    string savePrefabPath = AssetDatabase.GetAssetPath(prefab);
                    PrefabUtility.SaveAsPrefabAsset(newPrefab, savePrefabPath);
                    AssetDatabase.SaveAssets();
                    GameObject.DestroyImmediate(newPrefab);
                }
                completed++;
                EditorUtility.DisplayProgressBar("正在将数据写进对应的预置体", completed + "/" + total, completed / (float)total);
            }
            I18NEditor.SavePrefabI18NToJson();
            EditorUtility.ClearProgressBar();
            if (sccess)
            {
                Debug.Log("导入Excel表成功");
                //EditorUtility.DisplayDialog("提示", "导入Excel表成功", "确定");
            }
#endif
        }

        private static bool IsIndex(string value)
        {
            int index = 0;
            return int.TryParse(value, out index);
        }
    }
}
